/*******************************************************************************************
 * Copyright (c) 2006-2009 Alex Robson, Rob Simmons, Craig Israel, and Rachel Twyford
 *
 * Use of this software in any form requires that you have both 
 * read and agreed to the following terms:
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the "Software"), 
 * to deal in the Software without restriction, including without limitation 
 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions: 
 *
 * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, 
 * this list of conditions and the following disclaimer in the 
 * documentation and/or other materials provided with the distribution.
 * Neither the name of Nvigorate nor the names of its contributors may 
 * be used to endorse or promote products derived from this software without 
 * specific prior written permission. 
 *
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
 * DISCLAIMED. IN NO EVENT SHALL ANY CONTRIBUTOR BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * ****************************************************************************************/

using System;
using System.Collections.Generic;
using System.Data;
using Nvigorate.Data.Query;

namespace Nvigorate.Data
{
    public interface IDataInterface : IDisposable
    {
        /// <summary>
        /// If Cache is true, than DataInterface will cache -all- query results
        /// for later retrieval.
        /// </summary>
        bool CacheResults { get; set; }

        /// <summary>
        /// Handle to the IDbConnection object
        /// </summary>
        IDbConnection Connection { get; }

        IDatabaseProvider Provider { get; }

        /// <summary>
        /// Retrieves a list of stored procedures and their parameters from the database and
        /// caches each so they can be called in the future.
        /// </summary>
        void AddAllProcedures();

        /// <summary>
        /// Add a stored procedure to call in the future. This function will query the
        /// database for parameter names and types and cache the results.
        /// </summary>
        /// <param procedureName="procedureName">The case-sensitive name of the stored procedure</param>
        void AddProcedure(string procedureName);

        /// <summary>
        /// Add a stored procedure to call in the future. The parameter names should be
        /// listed in the order you will assign values to them.
        /// </summary>
        /// <param procedureName="name">The case-sensitive name of the stored procedure</param>
        /// <param parameterNames="parameterNames">The case-sensitive names of the stored procedure's parameters</param>
        /// <remarks>Deprecated: when possible, use AddProcedure(string procedureName)</remarks>
        void AddProcedure(string procedureName, params IDbDataParameter[] parameters);

        /// <summary>
        /// Adds a relationship to the specifed cached dataset.
        /// </summary>
        /// <param name="dataSetName">The name the dataset was cached by</param>
        /// <param name="relationName">The name of the relationship to create</param>
        /// <param name="parentTableName">The name of the parent table in the dataset</param>
        /// <param name="childTableName">The name of the child table in the dataset</param>
        /// <param name="parentColumn">The name of the parent table's column</param>
        /// <param name="childColumn">The name of the child table's column</param>
        /// <param name="nested">Specifies whether or not this relationship is nested.</param>
        /// <returns>A boolean indicated the success of adding the relationship</returns>
        bool AddRelationToDataSet(string dataSetName,
                                                  string relationName,
                                                  string parentTableName,
                                                  string childTableName,
                                                  string parentColumn,
                                                  string childColumn,
                                                  bool nested);

        /// <summary>
        /// Adds a relationship to the specifed cached dataset.
        /// </summary>
        /// <param name="dataSetName">The name the dataset was cached by</param>
        /// <param name="relationName">The name of the relationship to create</param>
        /// <param name="parentTableName">The name of the parent table in the dataset</param>
        /// <param name="childTableName">The name of the child table in the dataset</param>
        /// <param name="parentList">The name of the parent table's column</param>
        /// <param name="childList">The name of the child table's column</param>
        /// <param name="nested">Specifies whether or not this relationship is nested.</param>
        /// <returns>A boolean indicated the success of adding the relationship</returns>
        bool AddRelationToDataSet(string dataSetName,
                                                  string relationName,
                                                  string parentTableName,
                                                  string childTableName,
                                                  List<string> parentList,
                                                  List<string> childList,
                                                  bool nested);

        /// <summary>
        /// Adds a cached table to the cached dataset. Both objects must already exist or an error will occur.
        /// </summary>
        /// <param name="dataSetName">Name of the cached dataset</param>
        /// <param name="tableName">Name of the cached table</param>
        void AddTableToDataSet(string dataSetName, string tableName);

        /// <summary>
        /// Adds the list of cached tables to the cached dataset. All tables and the dataset must already exist or an error will occur.
        /// </summary>
        /// <param name="dataSetName">Name of the cached dataset</param>
        /// <param name="tableNames">Names of the cached tables</param>
        void AddTablesToDataSet(string dataSetName, params string[] tableNames);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dataSetName"></param>
        /// <returns></returns>
        bool CreateDataSet(string dataSetName);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dataSetName"></param>
        /// <param name="tableNames"></param>
        /// <returns></returns>
        bool CreateDataSet(string dataSetName, params string[] tableNames);

        int ExecuteCommand(string commandText, bool useTransaction);
        int ExecuteCommand(string commandText, bool useTransaction, List<IDbDataParameter> parameters);
        int ExecuteCommand(string commandText, bool useTransaction, Dictionary<string, object> parameters);
        int ExecuteCommand(string commandText, bool useTransaction, params object[] parameters);
        int ExecuteCommand(IQueryObject query, bool useTransaction);
        DataTable ExecuteCommandWithTableResult(IQueryObject query, bool useTransaction, string tableName);
        DataSet ExecuteCommandWithSetResult(IQueryObject query, bool useTransaction, string datasetName, List<string> tableNames);

        /// <summary>
        /// Creates a new table from an existing cached table using the provided filter and store
        /// it in the cache by the alias.
        /// </summary>
        /// <param name="filter">The SQL filter to apply against the sourceTable</param>
        /// <param name="sourceTable">The alias of the source table to create the new table from</param>
        /// <param name="tableName">The alias of the new table to create from the rows mathcing the filter</param>
        void ExtractTableByFilter(string filter, string sourceTable, string tableName);

        /// <summary>
        /// Returns an array of the rows matching the filter
        /// </summary>
        /// <param name="filter">The SQL filter to apply to the rows in the specified table</param>
        /// <param name="tableName">The alias of the cached table</param>
        /// <returns>A DataRow array containing rows which matched the filter</returns>
        DataRow[] GetRowsByFilter(string filter, string tableName);

        DataSet GetSet(string commandText, string datasetName, List<string> tableNames);

        DataSet GetSet(string commandText, string datasetName, List<string> tableNames,
                                       IEnumerable<IDbDataParameter> parameters);

        DataSet GetSet(string commandText, string datasetName, List<string> tableNames,
                                       Dictionary<string, object> parameters);

        DataSet GetSet(string commandText, string datasetName, List<string> tableNames,
                                       params object[] parameters);

        DataSet GetSet(IQueryObject query, string datasetName, List<string> tableNames);

        /// <summary>
        /// Retrieves the cached dataset specified
        /// </summary>
        /// <param name="datasetName">The name of the dataset</param>
        /// <returns>Cached dataset</returns>
        DataSet GetSet(string datasetName);

        DataTable GetTable(string commandText, string tableName);
        DataTable GetTable(string commandText, string tableName, List<IDbDataParameter> parameters);
        DataTable GetTable(string commandText, string tableName, Dictionary<string, object> parameters);
        DataTable GetTable(string commandText, string tableName, params object[] parameters);
        DataTable GetTable(string tableName);
        DataTable GetTable(IQueryObject query, string tableName);
        object GetValue(string commandText);
        object GetValue(string commandText, IEnumerable<IDbDataParameter> parameters);
        object GetValue(string commandText, Dictionary<string, object> parameters);
        object GetValue(string commandText, params object[] parameters);
        object GetValue(IQueryObject query);

        /// <summary>
        /// Returns an array of values for a specifc column across all rows in the referenced table
        /// </summary>
        /// <param name="tableName">The alias of the table to pull the column values from</param>
        /// <param name="columnName">The name of the column to pull values from</param>
        /// <returns></returns>
        object[] GetValuesByColumn(string tableName, string columnName);

        /// <summary>
        /// Returns an array of values for a specifc column across all rows in the referenced table
        /// </summary>
        /// <param name="tableName">The alias of the table to pull the column values from</param>
        /// <param name="columnOrdinal">The ordinal index of the column to pull values from</param>
        /// <returns></returns>
        object[] GetValuesByColumn(string tableName, int columnOrdinal);

        /// <summary>
        /// Returns the number of RecordsInTable (rows) in a given strTableName
        /// </summary>
        /// <param name="tableName">The strTableName name</param>
        /// <returns>The number of rows in a strTableName</returns>
        int RecordsInTable(string tableName);

        /// <summary>
        /// Removes the specified stored set from the dataset cache
        /// </summary>
        /// <param name="datasetName">The alias of the dataset to remove from the cache</param>
        void RemoveSet(string datasetName);

        /// <summary>
        /// Removes the specified stored table from the table cache
        /// </summary>
        /// <param name="tableName">The alias of the table to remove from the cache</param>
        void RemoveTable(string tableName);

        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        /// <filterpriority>2</filterpriority>
        void Dispose();
    }
}